/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.engine.core.be;

import com.inspur.edp.bef.api.be.IBENodeEntity;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.internalmgraction.TccSettingElement;
import com.inspur.edp.bef.core.be.BusinessEntity;
import com.inspur.edp.bef.core.be.builtinimpls.BeEntityCacheInfo;
import com.inspur.edp.bef.core.determination.builtinimpls.BefAfterSaveDtmAssembler;
import com.inspur.edp.bef.core.tcc.builtinimpls.BefTccHandlerAssembler;
import com.inspur.edp.bef.engine.common.GspBizEntityUtil;
import com.inspur.edp.bef.engine.core.BefEngineInfoCache;
import com.inspur.edp.bef.engine.core.dtm.*;
import com.inspur.edp.bef.engine.core.val.AfterModifyVal;
import com.inspur.edp.bef.engine.core.val.AfterSaveVal;
import com.inspur.edp.bef.engine.core.val.BeforeSaveVal;
import com.inspur.edp.bef.engine.entity.BeModelResInfo;
import com.inspur.edp.bef.engine.entity.EngineChildAccessor;
import com.inspur.edp.bef.engine.entity.EngineChildData;
import com.inspur.edp.bef.engine.entity.EngineRootData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.entityaction.CefDataTypeAction;
import com.inspur.edp.cef.spi.validation.IEntityRTValidationAssembler;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import org.springframework.util.StringUtils;

public class EngineBusinessEntity extends BusinessEntity {

    private final GspBusinessEntity be;
    private BeModelResInfo modelResInfo;
    private GspMetadata metadata;

    public EngineBusinessEntity(GspBusinessEntity be, BeModelResInfo modelResInfo, String dataId) {
        super(dataId);
        this.be = be;
        this.modelResInfo = modelResInfo;
    }

    public EngineBusinessEntity(GspBusinessEntity be, BeModelResInfo modelResInfo, String dataId, GspMetadata gspMetadata) {
        super(dataId);
        this.be = be;
        this.modelResInfo = modelResInfo;
        this.metadata = gspMetadata;
    }

    @Override
    protected int getVersion() {
        return 1;
    }

    @Override
    public String getNodeCode() {
        return be.getMainObject().getCode();
    }

    @Override
    public CefEntityResInfoImpl getEntityResInfo() {
        return (CefEntityResInfoImpl) modelResInfo.getCustomResource(getNodeCode());
    }

    @Override
    protected IEntityData innerCreateEntityData(String id) {
        EngineRootData data = new EngineRootData(be.getMainObject(), getEntityResInfo());
        data.setID(id);
        GspBizEntityUtil.initBeDataValue(be.getMainObject(), data, null, getEntityResInfo());
        return data;

    }

    @Override
    public IEntityData innerCreateChildEntityData(String childCode, String id) {
        IGspCommonObject childNode = GspBizEntityUtil.findNode(be, childCode);
        EngineChildData data = new EngineChildData(childNode,
                (CefEntityResInfoImpl) modelResInfo.getCustomResource(childNode.getCode()));
        data.setID(id);
        GspBizEntityUtil.initBeDataValue(childNode, data, null, (CefEntityResInfoImpl) modelResInfo.getCustomResource(childNode.getCode()));
        return data;
    }

    @Override
    public IEntityData innerCreateChildAccessor(String childCode, IEntityData data) {
        IGspCommonObject childNode = GspBizEntityUtil.findNode(be, childCode);
        return new EngineChildAccessor(childNode, data,
                (CefEntityResInfoImpl) modelResInfo.getCustomResource(childNode.getCode()));
    }

    @Override
    protected IBENodeEntity innerGetChildBEEntity(String childCode, String id) {
        EngineChildEntity entity = new EngineChildEntity(be, GspBizEntityUtil.findNode(be, childCode)
                , id, getEntityResInfo(), metadata);
        entity.setContext(createChildEntityContext(childCode, id));
        entity.setParent(this);
        return entity;
    }

    @Override
    public void assignDefaultValue(com.inspur.edp.cef.entity.entity.IEntityData data) {
        GspBizEntityUtil.assignDefaultValue(be.getMainObject(), data);
    }

    @Override
    protected com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler createBeforeSaveDtmAssembler() {
        return new BeforeSaveDtm(be.getMainObject());
    }

    protected IEntityRTDtmAssembler createAfterSaveDtmAssembler() {
        return new AfterSaveDtm(be.getMainObject());
    }
    @Override
    protected com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler createAfterModifyDtmAssembler() {
        return new AfterModifyDtm(be.getMainObject());
    }

    @Override
    protected com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler createRetrieveDefaultDtmAssembler() {
        return new AfterCreateDtm(be.getMainObject());
    }

    @Override
    protected com.inspur.edp.cef.spi.validation.IEntityRTValidationAssembler createAfterModifyValidationAssembler() {
        return new AfterModifyVal(be, be.getMainObject());
    }

    @Override
    protected com.inspur.edp.cef.spi.validation.IEntityRTValidationAssembler createBeforeSaveValidationAssembler() {
        return new BeforeSaveVal(be, be.getMainObject());
    }

    @Override
    protected IEntityRTValidationAssembler createAfterSaveValAssembler() {
        return new AfterSaveVal(be, be.getMainObject());
    }

    @Override
    public IEntityRTDtmAssembler createAfterLoadingDtmAssembler() {
        return new AfterLoadingDtm(be.getMainObject());
    }

    @Override
    protected IEntityRTDtmAssembler createAfterQueryDtmAssembler() {
        return new AfterQueryDtm(be.getMainObject());
    }

    @Override
    public IEntityRTDtmAssembler createOnCancelDtmAssembler() {
        return new OnCancelDtm(be.getMainObject());
    }

    @Override
    public Object executeBizAction(String actionCode, Object... pars) {
        getBEContext().checkDataAuthority(actionCode);
        CefDataTypeAction action = GspBizEntityUtil
                .instantiateBizAction(be.getMainObject(), actionCode, getBEContext(), pars);
        return execute(action);
    }

    @Override
    protected BeEntityCacheInfo getBeEntityCacheInfo() {
        if (metadata != null && metadata.getProperties() != null && metadata.getProperties().getCacheVersion() != null && !"".equals(metadata.getProperties().getCacheVersion())) {
            return BefEngineInfoCache.getBefEngineInfo(be.getID(), metadata.getProperties().getCacheVersion()).getBeEntityCacheInfo(be.getMainObject().getID());
        } else {
            return BefEngineInfoCache.getBefEngineInfo(be.getID()).getBeEntityCacheInfo(be.getMainObject().getID());
        }
    }

    @Override
    protected BefTccHandlerAssembler createTccAssembler() {
        BefTccHandlerAssembler rez = super.createTccAssembler();
        if (be.isTccSupported() && (!be.isAutoCancel() || !be.isAutoComplete())
                && be.getMainObject().getTccSettings() != null) {
            for (TccSettingElement tccSetting : be.getMainObject().getTccSettings()) {
                if (tccSetting.getTccAction() == null || StringUtils
                        .isEmpty(tccSetting.getTccAction().getComponentId())) {
                    GspBizEntityUtil.throwNoTccComp(be.getMainObject(), tccSetting);
                }
                rez.addHandler(tccSetting.getCode(), tccSetting.getTccAction().getComponentId());
            }
        }
        return rez;
    }
}
